-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[HLSL] [SPIR-V] Add counter member for typed buffer #161414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-spir-v @llvm/pr-subscribers-hlsl Author: Steven Perron (s-perron) ChangesThis is part 1 of implementing the typed buffer counters proposal: This patch adds the initial plumbing for supporting counter variables Patch is 30.86 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161414.diff 17 Files Affected:
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index b02d9c7499fe5..b60ef6911d84a 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -6700,15 +6700,21 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
LLVM_PREFERRED_TYPE(bool)
uint8_t RawBuffer : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ uint8_t IsCounter : 1;
+
Attributes(llvm::dxil::ResourceClass ResourceClass, bool IsROV = false,
- bool RawBuffer = false)
- : ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer) {}
+ bool RawBuffer = false, bool IsCounter = false)
+ : ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer),
+ IsCounter(IsCounter) {}
- Attributes() : Attributes(llvm::dxil::ResourceClass::UAV, false, false) {}
+ Attributes()
+ : Attributes(llvm::dxil::ResourceClass::UAV, false, false, false) {}
friend bool operator==(const Attributes &LHS, const Attributes &RHS) {
- return std::tie(LHS.ResourceClass, LHS.IsROV, LHS.RawBuffer) ==
- std::tie(RHS.ResourceClass, RHS.IsROV, RHS.RawBuffer);
+ return std::tie(LHS.ResourceClass, LHS.IsROV, LHS.RawBuffer,
+ LHS.IsCounter) == std::tie(RHS.ResourceClass, RHS.IsROV,
+ RHS.RawBuffer, RHS.IsCounter);
}
friend bool operator!=(const Attributes &LHS, const Attributes &RHS) {
return !(LHS == RHS);
@@ -6749,6 +6755,7 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
ID.AddInteger(static_cast<uint32_t>(Attrs.ResourceClass));
ID.AddBoolean(Attrs.IsROV);
ID.AddBoolean(Attrs.RawBuffer);
+ ID.AddBoolean(Attrs.IsCounter);
}
static bool classof(const Type *T) {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index b3932a67db69d..9dc85fb88e267 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -662,6 +662,9 @@ let Class = HLSLAttributedResourceType in {
def : Property<"rawBuffer", Bool> {
let Read = [{ node->getAttrs().RawBuffer }];
}
+ def : Property<"isCounter", Bool> {
+ let Read = [{ node->getAttrs().IsCounter }];
+ }
def : Property<"wrappedTy", QualType> {
let Read = [{ node->getWrappedType() }];
}
@@ -669,7 +672,7 @@ let Class = HLSLAttributedResourceType in {
let Read = [{ node->getContainedType() }];
}
def : Creator<[{
- HLSLAttributedResourceType::Attributes attrs(static_cast<llvm::dxil::ResourceClass>(resClass), isROV, rawBuffer);
+ HLSLAttributedResourceType::Attributes attrs(static_cast<llvm::dxil::ResourceClass>(resClass), isROV, rawBuffer, isCounter);
return ctx.getHLSLAttributedResourceType(wrappedTy, containedTy, attrs);
}]>;
}
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 2623f9ff6972f..1d6f4e809a1fa 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -5059,6 +5059,12 @@ def HLSLRawBuffer : TypeAttr {
let Documentation = [InternalOnly];
}
+def HLSLIsCounter : TypeAttr {
+ let Spellings = [CXX11<"hlsl", "is_counter">];
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
def HLSLGroupSharedAddressSpace : TypeAttr {
let Spellings = [CustomKeyword<"groupshared">];
let Subjects = SubjectList<[Var]>;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 2173aed5b45af..844db79f18a4a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4624,6 +4624,8 @@ void CXXNameMangler::mangleType(const HLSLAttributedResourceType *T) {
Str += "_ROV";
if (Attrs.RawBuffer)
Str += "_Raw";
+ if (Attrs.IsCounter)
+ Str += "_Counter";
if (T->hasContainedType())
Str += "_CT";
mangleVendorQualifier(Str);
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index cd59678d67f2f..b2ba569843897 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2033,6 +2033,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::HLSLROV:
case attr::HLSLRawBuffer:
case attr::HLSLContainedType:
+ case attr::HLSLIsCounter:
llvm_unreachable("HLSL resource type attributes handled separately");
case attr::OpenCLPrivateAddressSpace:
@@ -2181,6 +2182,8 @@ void TypePrinter::printHLSLAttributedResourceAfter(
OS << " [[hlsl::is_rov]]";
if (Attrs.RawBuffer)
OS << " [[hlsl::raw_buffer]]";
+ if (Attrs.IsCounter)
+ OS << " [[hlsl::is_counter]]";
QualType ContainedTy = T->getContainedType();
if (!ContainedTy.isNull()) {
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index 2e3fc53c58edc..4aa63143a66cd 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -486,6 +486,12 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ContainedTy, CGM);
}
+ if (ResAttrs.IsCounter) {
+ llvm::Type *ElemType = llvm::Type::getInt32Ty(Ctx);
+ uint32_t StorageClass = /* StorageBuffer storage class */ 12;
+ return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer", {ElemType},
+ {StorageClass, true});
+ }
llvm::Type *ElemType = CGM.getTypes().ConvertTypeForMem(ContainedTy);
llvm::ArrayType *RuntimeArrayType = llvm::ArrayType::get(ElemType, 0);
uint32_t StorageClass = /* StorageBuffer storage class */ 12;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 5eafd03d89efe..847f4a26c8788 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -138,7 +138,16 @@ struct BuiltinTypeMethodBuilder {
// LastStmt - refers to the last statement in the method body; referencing
// LastStmt will remove the statement from the method body since
// it will be linked from the new expression being constructed.
- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
+ enum class PlaceHolder {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ Handle = 128,
+ CounterHandle,
+ LastStmt
+ };
Expr *convertPlaceholder(PlaceHolder PH);
Expr *convertPlaceholder(LocalVar &Var);
@@ -178,10 +187,17 @@ struct BuiltinTypeMethodBuilder {
template <typename ResourceT, typename ValueT>
BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord,
ValueT HandleValue);
+ template <typename T>
+ BuiltinTypeMethodBuilder &
+ accessCounterHandleFieldOnResource(T ResourceRecord);
+ template <typename ResourceT, typename ValueT>
+ BuiltinTypeMethodBuilder &
+ setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
BuiltinTypeMethodBuilder &returnThis();
BuiltinTypeDeclBuilder &finalize();
Expr *getResourceHandleExpr();
+ Expr *getResourceCounterHandleExpr();
private:
void createDecl();
@@ -346,6 +362,8 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) {
Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
if (PH == PlaceHolder::Handle)
return getResourceHandleExpr();
+ if (PH == PlaceHolder::CounterHandle)
+ return getResourceCounterHandleExpr();
if (PH == PlaceHolder::LastStmt) {
assert(!StmtsList.empty() && "no statements in the list");
@@ -467,6 +485,18 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
OK_Ordinary);
}
+Expr *BuiltinTypeMethodBuilder::getResourceCounterHandleExpr() {
+ ensureCompleteDecl();
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ CXXThisExpr *This = CXXThisExpr::Create(
+ AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ return MemberExpr::CreateImplicit(AST, This, false, HandleField,
+ HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+}
+
BuiltinTypeMethodBuilder &
BuiltinTypeMethodBuilder::declareLocalVar(LocalVar &Var) {
ensureCompleteDecl();
@@ -583,6 +613,44 @@ BuiltinTypeMethodBuilder::setHandleFieldOnResource(ResourceT ResourceRecord,
return *this;
}
+template <typename T>
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::accessCounterHandleFieldOnResource(T ResourceRecord) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ StmtsList.push_back(HandleExpr);
+ return *this;
+}
+
+template <typename ResourceT, typename ValueT>
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::setCounterHandleFieldOnResource(
+ ResourceT ResourceRecord, ValueT HandleValue) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+ Expr *HandleValueExpr = convertPlaceholder(HandleValue);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ Stmt *AssignStmt = BinaryOperator::Create(
+ DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
+ BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
+ ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride());
+ StmtsList.push_back(AssignStmt);
+ return *this;
+}
+
template <typename T>
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
ensureCompleteDecl();
@@ -745,6 +813,30 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
return *this;
}
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
+ ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
+ assert(!Record->isCompleteDefinition() && "record is already complete");
+
+ ASTContext &Ctx = SemaRef.getASTContext();
+ TypeSourceInfo *ElementTypeInfo =
+ Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
+
+ // add handle member with resource type attributes
+ QualType AttributedResTy = QualType();
+ SmallVector<const Attr *> Attrs = {
+ HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
+ IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
+ RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
+ ElementTypeInfo
+ ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
+ : nullptr,
+ HLSLIsCounterAttr::CreateImplicit(Ctx)};
+ if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
+ AttributedResTy))
+ addMemberVariable("__counter_handle", AttributedResTy, {}, Access);
+ return *this;
+}
+
// Adds default constructor to the resource class:
// Resource::Resource()
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
@@ -848,12 +940,18 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
- return BuiltinTypeMethodBuilder(*this, /*Name=*/"", AST.VoidTy,
- /*IsConst=*/false, /*IsCtor=*/true)
- .addParam("other", ConstRecordRefType)
+ BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
+ /*IsConst=*/false, /*IsCtor=*/true);
+ MMB.addParam("other", ConstRecordRefType)
.accessHandleFieldOnResource(PH::_0)
- .assign(PH::Handle, PH::LastStmt)
- .finalize();
+ .assign(PH::Handle, PH::LastStmt);
+
+ if (getResourceCounterHandleField()) {
+ MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
+ PH::LastStmt);
+ }
+
+ return MMB.finalize();
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
@@ -868,12 +966,17 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
DeclarationName Name = AST.DeclarationNames.getCXXOperatorName(OO_Equal);
- return BuiltinTypeMethodBuilder(*this, Name, RecordRefType)
- .addParam("other", ConstRecordRefType)
+ BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
+ MMB.addParam("other", ConstRecordRefType)
.accessHandleFieldOnResource(PH::_0)
- .assign(PH::Handle, PH::LastStmt)
- .returnThis()
- .finalize();
+ .assign(PH::Handle, PH::LastStmt);
+
+ if (getResourceCounterHandleField()) {
+ MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
+ PH::LastStmt);
+ }
+
+ return MMB.returnThis().finalize();
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
@@ -909,6 +1012,13 @@ FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
return I->second;
}
+FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
+ auto I = Fields.find("__counter_handle");
+ if (I == Fields.end())
+ return nullptr;
+ return I->second;
+}
+
QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
assert(Template && "record it not a template");
if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 9448af13530cb..a62088e0ef551 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -74,6 +74,9 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &
addHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer,
AccessSpecifier Access = AccessSpecifier::AS_private);
+ BuiltinTypeDeclBuilder &
+ addCounterHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer,
+ AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &addArraySubscriptOperators();
// Builtin types constructors
@@ -96,6 +99,7 @@ class BuiltinTypeDeclBuilder {
private:
FieldDecl *getResourceHandleField() const;
+ FieldDecl *getResourceCounterHandleField() const;
QualType getFirstTemplateTypeParam();
QualType getHandleElementType();
Expr *getConstantIntExpr(int value);
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 781f0445d0b61..650ad386f074b 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -126,16 +126,31 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
}
/// Set up common members and attributes for buffer types
+static bool resourceHasCounter(const CXXRecordDecl *Decl) {
+ StringRef Name = Decl->getName();
+ return Name == "RWStructuredBuffer" || Name == "AppendStructuredBuffer" ||
+ Name == "ConsumeStructuredBuffer";
+}
+
static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
ResourceClass RC, bool IsROV,
bool RawBuffer) {
- return BuiltinTypeDeclBuilder(S, Decl)
- .addHandleMember(RC, IsROV, RawBuffer)
- .addDefaultHandleConstructor()
+ // TODO: This should be cleaned up. We should have a function
+ // addCounterHandleMembers that will add the main handle, and if necessary add
+ // the counter handle.
+ BuiltinTypeDeclBuilder BTB(S, Decl);
+ BTB.addHandleMember(RC, IsROV, RawBuffer);
+
+ if (resourceHasCounter(Decl)) {
+ BTB.addCounterHandleMember(RC, IsROV, RawBuffer);
+ }
+
+ BTB.addDefaultHandleConstructor()
.addCopyConstructor()
.addCopyAssignmentOperator()
.addCreateFromBinding()
.addCreateFromImplicitBinding();
+ return BTB;
}
// This function is responsible for constructing the constraint expression for
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 55be036207eec..190d2dec8758a 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1811,6 +1811,13 @@ bool clang::CreateHLSLAttributedResourceType(
}
ResAttrs.RawBuffer = true;
break;
+ case attr::HLSLIsCounter:
+ if (ResAttrs.IsCounter) {
+ S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
+ return false;
+ }
+ ResAttrs.IsCounter = true;
+ break;
case attr::HLSLContainedType: {
const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
QualType Ty = CTAttr->getType();
@@ -1903,6 +1910,10 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {
A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
break;
+ case ParsedAttr::AT_HLSLIsCounter:
+ A = HLSLIsCounterAttr::Create(getASTContext(), ACI);
+ break;
+
case ParsedAttr::AT_HLSLContainedType: {
if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index a490b22ab437b..a0cad2c7f1e8b 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -12,7 +12,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RWStructuredBuffer %s | FileCheck -DRESOURCE=RWStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-COUNTER,CHECK-LOAD %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-COUNTER,CHECK-LOAD,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \
@@ -20,7 +20,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-APPEND %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-APPEND,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=ConsumeStructuredBuffer %s | FileCheck -DRESOURCE=ConsumeStructuredBuffer \
@@ -28,7 +28,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=ConsumeStructuredBuffer %s | FileCheck -DRESOURCE=ConsumeStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-CONSUME %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-CONSUME,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=RasterizerOrderedStructuredBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedStructuredBuffer \
@@ -113,6 +113,11 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
+// CHECK-COUNTER-HANDLE-NEXT: BinaryOperator {{.*}} '='
+// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} lvalue .__counter_handle
+// CHECK-COUNTER-HANDLE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} lvalu...
[truncated]
|
@llvm/pr-subscribers-clang-codegen Author: Steven Perron (s-perron) ChangesThis is part 1 of implementing the typed buffer counters proposal: This patch adds the initial plumbing for supporting counter variables Patch is 30.86 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161414.diff 17 Files Affected:
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index b02d9c7499fe5..b60ef6911d84a 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -6700,15 +6700,21 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
LLVM_PREFERRED_TYPE(bool)
uint8_t RawBuffer : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ uint8_t IsCounter : 1;
+
Attributes(llvm::dxil::ResourceClass ResourceClass, bool IsROV = false,
- bool RawBuffer = false)
- : ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer) {}
+ bool RawBuffer = false, bool IsCounter = false)
+ : ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer),
+ IsCounter(IsCounter) {}
- Attributes() : Attributes(llvm::dxil::ResourceClass::UAV, false, false) {}
+ Attributes()
+ : Attributes(llvm::dxil::ResourceClass::UAV, false, false, false) {}
friend bool operator==(const Attributes &LHS, const Attributes &RHS) {
- return std::tie(LHS.ResourceClass, LHS.IsROV, LHS.RawBuffer) ==
- std::tie(RHS.ResourceClass, RHS.IsROV, RHS.RawBuffer);
+ return std::tie(LHS.ResourceClass, LHS.IsROV, LHS.RawBuffer,
+ LHS.IsCounter) == std::tie(RHS.ResourceClass, RHS.IsROV,
+ RHS.RawBuffer, RHS.IsCounter);
}
friend bool operator!=(const Attributes &LHS, const Attributes &RHS) {
return !(LHS == RHS);
@@ -6749,6 +6755,7 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
ID.AddInteger(static_cast<uint32_t>(Attrs.ResourceClass));
ID.AddBoolean(Attrs.IsROV);
ID.AddBoolean(Attrs.RawBuffer);
+ ID.AddBoolean(Attrs.IsCounter);
}
static bool classof(const Type *T) {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index b3932a67db69d..9dc85fb88e267 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -662,6 +662,9 @@ let Class = HLSLAttributedResourceType in {
def : Property<"rawBuffer", Bool> {
let Read = [{ node->getAttrs().RawBuffer }];
}
+ def : Property<"isCounter", Bool> {
+ let Read = [{ node->getAttrs().IsCounter }];
+ }
def : Property<"wrappedTy", QualType> {
let Read = [{ node->getWrappedType() }];
}
@@ -669,7 +672,7 @@ let Class = HLSLAttributedResourceType in {
let Read = [{ node->getContainedType() }];
}
def : Creator<[{
- HLSLAttributedResourceType::Attributes attrs(static_cast<llvm::dxil::ResourceClass>(resClass), isROV, rawBuffer);
+ HLSLAttributedResourceType::Attributes attrs(static_cast<llvm::dxil::ResourceClass>(resClass), isROV, rawBuffer, isCounter);
return ctx.getHLSLAttributedResourceType(wrappedTy, containedTy, attrs);
}]>;
}
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 2623f9ff6972f..1d6f4e809a1fa 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -5059,6 +5059,12 @@ def HLSLRawBuffer : TypeAttr {
let Documentation = [InternalOnly];
}
+def HLSLIsCounter : TypeAttr {
+ let Spellings = [CXX11<"hlsl", "is_counter">];
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
def HLSLGroupSharedAddressSpace : TypeAttr {
let Spellings = [CustomKeyword<"groupshared">];
let Subjects = SubjectList<[Var]>;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 2173aed5b45af..844db79f18a4a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4624,6 +4624,8 @@ void CXXNameMangler::mangleType(const HLSLAttributedResourceType *T) {
Str += "_ROV";
if (Attrs.RawBuffer)
Str += "_Raw";
+ if (Attrs.IsCounter)
+ Str += "_Counter";
if (T->hasContainedType())
Str += "_CT";
mangleVendorQualifier(Str);
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index cd59678d67f2f..b2ba569843897 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2033,6 +2033,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::HLSLROV:
case attr::HLSLRawBuffer:
case attr::HLSLContainedType:
+ case attr::HLSLIsCounter:
llvm_unreachable("HLSL resource type attributes handled separately");
case attr::OpenCLPrivateAddressSpace:
@@ -2181,6 +2182,8 @@ void TypePrinter::printHLSLAttributedResourceAfter(
OS << " [[hlsl::is_rov]]";
if (Attrs.RawBuffer)
OS << " [[hlsl::raw_buffer]]";
+ if (Attrs.IsCounter)
+ OS << " [[hlsl::is_counter]]";
QualType ContainedTy = T->getContainedType();
if (!ContainedTy.isNull()) {
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index 2e3fc53c58edc..4aa63143a66cd 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -486,6 +486,12 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ContainedTy, CGM);
}
+ if (ResAttrs.IsCounter) {
+ llvm::Type *ElemType = llvm::Type::getInt32Ty(Ctx);
+ uint32_t StorageClass = /* StorageBuffer storage class */ 12;
+ return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer", {ElemType},
+ {StorageClass, true});
+ }
llvm::Type *ElemType = CGM.getTypes().ConvertTypeForMem(ContainedTy);
llvm::ArrayType *RuntimeArrayType = llvm::ArrayType::get(ElemType, 0);
uint32_t StorageClass = /* StorageBuffer storage class */ 12;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 5eafd03d89efe..847f4a26c8788 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -138,7 +138,16 @@ struct BuiltinTypeMethodBuilder {
// LastStmt - refers to the last statement in the method body; referencing
// LastStmt will remove the statement from the method body since
// it will be linked from the new expression being constructed.
- enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
+ enum class PlaceHolder {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ Handle = 128,
+ CounterHandle,
+ LastStmt
+ };
Expr *convertPlaceholder(PlaceHolder PH);
Expr *convertPlaceholder(LocalVar &Var);
@@ -178,10 +187,17 @@ struct BuiltinTypeMethodBuilder {
template <typename ResourceT, typename ValueT>
BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord,
ValueT HandleValue);
+ template <typename T>
+ BuiltinTypeMethodBuilder &
+ accessCounterHandleFieldOnResource(T ResourceRecord);
+ template <typename ResourceT, typename ValueT>
+ BuiltinTypeMethodBuilder &
+ setCounterHandleFieldOnResource(ResourceT ResourceRecord, ValueT HandleValue);
template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
BuiltinTypeMethodBuilder &returnThis();
BuiltinTypeDeclBuilder &finalize();
Expr *getResourceHandleExpr();
+ Expr *getResourceCounterHandleExpr();
private:
void createDecl();
@@ -346,6 +362,8 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) {
Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
if (PH == PlaceHolder::Handle)
return getResourceHandleExpr();
+ if (PH == PlaceHolder::CounterHandle)
+ return getResourceCounterHandleExpr();
if (PH == PlaceHolder::LastStmt) {
assert(!StmtsList.empty() && "no statements in the list");
@@ -467,6 +485,18 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
OK_Ordinary);
}
+Expr *BuiltinTypeMethodBuilder::getResourceCounterHandleExpr() {
+ ensureCompleteDecl();
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ CXXThisExpr *This = CXXThisExpr::Create(
+ AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ return MemberExpr::CreateImplicit(AST, This, false, HandleField,
+ HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+}
+
BuiltinTypeMethodBuilder &
BuiltinTypeMethodBuilder::declareLocalVar(LocalVar &Var) {
ensureCompleteDecl();
@@ -583,6 +613,44 @@ BuiltinTypeMethodBuilder::setHandleFieldOnResource(ResourceT ResourceRecord,
return *this;
}
+template <typename T>
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::accessCounterHandleFieldOnResource(T ResourceRecord) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ MemberExpr *HandleExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ StmtsList.push_back(HandleExpr);
+ return *this;
+}
+
+template <typename ResourceT, typename ValueT>
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::setCounterHandleFieldOnResource(
+ ResourceT ResourceRecord, ValueT HandleValue) {
+ ensureCompleteDecl();
+
+ Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+ Expr *HandleValueExpr = convertPlaceholder(HandleValue);
+
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ FieldDecl *HandleField = DeclBuilder.getResourceCounterHandleField();
+ MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
+ AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+ OK_Ordinary);
+ Stmt *AssignStmt = BinaryOperator::Create(
+ DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr,
+ BO_Assign, HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
+ ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride());
+ StmtsList.push_back(AssignStmt);
+ return *this;
+}
+
template <typename T>
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
ensureCompleteDecl();
@@ -745,6 +813,30 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember(
return *this;
}
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember(
+ ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
+ assert(!Record->isCompleteDefinition() && "record is already complete");
+
+ ASTContext &Ctx = SemaRef.getASTContext();
+ TypeSourceInfo *ElementTypeInfo =
+ Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
+
+ // add handle member with resource type attributes
+ QualType AttributedResTy = QualType();
+ SmallVector<const Attr *> Attrs = {
+ HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
+ IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
+ RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
+ ElementTypeInfo
+ ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
+ : nullptr,
+ HLSLIsCounterAttr::CreateImplicit(Ctx)};
+ if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
+ AttributedResTy))
+ addMemberVariable("__counter_handle", AttributedResTy, {}, Access);
+ return *this;
+}
+
// Adds default constructor to the resource class:
// Resource::Resource()
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
@@ -848,12 +940,18 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
- return BuiltinTypeMethodBuilder(*this, /*Name=*/"", AST.VoidTy,
- /*IsConst=*/false, /*IsCtor=*/true)
- .addParam("other", ConstRecordRefType)
+ BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy,
+ /*IsConst=*/false, /*IsCtor=*/true);
+ MMB.addParam("other", ConstRecordRefType)
.accessHandleFieldOnResource(PH::_0)
- .assign(PH::Handle, PH::LastStmt)
- .finalize();
+ .assign(PH::Handle, PH::LastStmt);
+
+ if (getResourceCounterHandleField()) {
+ MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
+ PH::LastStmt);
+ }
+
+ return MMB.finalize();
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
@@ -868,12 +966,17 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
DeclarationName Name = AST.DeclarationNames.getCXXOperatorName(OO_Equal);
- return BuiltinTypeMethodBuilder(*this, Name, RecordRefType)
- .addParam("other", ConstRecordRefType)
+ BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType);
+ MMB.addParam("other", ConstRecordRefType)
.accessHandleFieldOnResource(PH::_0)
- .assign(PH::Handle, PH::LastStmt)
- .returnThis()
- .finalize();
+ .assign(PH::Handle, PH::LastStmt);
+
+ if (getResourceCounterHandleField()) {
+ MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle,
+ PH::LastStmt);
+ }
+
+ return MMB.returnThis().finalize();
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
@@ -909,6 +1012,13 @@ FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
return I->second;
}
+FieldDecl *BuiltinTypeDeclBuilder::getResourceCounterHandleField() const {
+ auto I = Fields.find("__counter_handle");
+ if (I == Fields.end())
+ return nullptr;
+ return I->second;
+}
+
QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
assert(Template && "record it not a template");
if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 9448af13530cb..a62088e0ef551 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -74,6 +74,9 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &
addHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer,
AccessSpecifier Access = AccessSpecifier::AS_private);
+ BuiltinTypeDeclBuilder &
+ addCounterHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer,
+ AccessSpecifier Access = AccessSpecifier::AS_private);
BuiltinTypeDeclBuilder &addArraySubscriptOperators();
// Builtin types constructors
@@ -96,6 +99,7 @@ class BuiltinTypeDeclBuilder {
private:
FieldDecl *getResourceHandleField() const;
+ FieldDecl *getResourceCounterHandleField() const;
QualType getFirstTemplateTypeParam();
QualType getHandleElementType();
Expr *getConstantIntExpr(int value);
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 781f0445d0b61..650ad386f074b 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -126,16 +126,31 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
}
/// Set up common members and attributes for buffer types
+static bool resourceHasCounter(const CXXRecordDecl *Decl) {
+ StringRef Name = Decl->getName();
+ return Name == "RWStructuredBuffer" || Name == "AppendStructuredBuffer" ||
+ Name == "ConsumeStructuredBuffer";
+}
+
static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
ResourceClass RC, bool IsROV,
bool RawBuffer) {
- return BuiltinTypeDeclBuilder(S, Decl)
- .addHandleMember(RC, IsROV, RawBuffer)
- .addDefaultHandleConstructor()
+ // TODO: This should be cleaned up. We should have a function
+ // addCounterHandleMembers that will add the main handle, and if necessary add
+ // the counter handle.
+ BuiltinTypeDeclBuilder BTB(S, Decl);
+ BTB.addHandleMember(RC, IsROV, RawBuffer);
+
+ if (resourceHasCounter(Decl)) {
+ BTB.addCounterHandleMember(RC, IsROV, RawBuffer);
+ }
+
+ BTB.addDefaultHandleConstructor()
.addCopyConstructor()
.addCopyAssignmentOperator()
.addCreateFromBinding()
.addCreateFromImplicitBinding();
+ return BTB;
}
// This function is responsible for constructing the constraint expression for
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 55be036207eec..190d2dec8758a 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1811,6 +1811,13 @@ bool clang::CreateHLSLAttributedResourceType(
}
ResAttrs.RawBuffer = true;
break;
+ case attr::HLSLIsCounter:
+ if (ResAttrs.IsCounter) {
+ S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;
+ return false;
+ }
+ ResAttrs.IsCounter = true;
+ break;
case attr::HLSLContainedType: {
const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
QualType Ty = CTAttr->getType();
@@ -1903,6 +1910,10 @@ bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {
A = HLSLRawBufferAttr::Create(getASTContext(), ACI);
break;
+ case ParsedAttr::AT_HLSLIsCounter:
+ A = HLSLIsCounterAttr::Create(getASTContext(), ACI);
+ break;
+
case ParsedAttr::AT_HLSLContainedType: {
if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {
Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index a490b22ab437b..a0cad2c7f1e8b 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -12,7 +12,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RWStructuredBuffer %s | FileCheck -DRESOURCE=RWStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-COUNTER,CHECK-LOAD %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-COUNTER,CHECK-LOAD,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \
@@ -20,7 +20,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-APPEND %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-APPEND,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=ConsumeStructuredBuffer %s | FileCheck -DRESOURCE=ConsumeStructuredBuffer \
@@ -28,7 +28,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=ConsumeStructuredBuffer %s | FileCheck -DRESOURCE=ConsumeStructuredBuffer \
-// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-CONSUME %s
+// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-CONSUME,CHECK-COUNTER-HANDLE %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=RasterizerOrderedStructuredBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedStructuredBuffer \
@@ -113,6 +113,11 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
+// CHECK-COUNTER-HANDLE-NEXT: BinaryOperator {{.*}} '='
+// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} lvalue .__counter_handle
+// CHECK-COUNTER-HANDLE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} lvalu...
[truncated]
|
cc11d49
to
b562d70
Compare
This is part 1 of implementing the typed buffer counters proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0023-typed-buffer-counters.md This patch adds the initial plumbing for supporting counter variables associated with structured buffers for the SPIR-V backend. It introduces an `IsCounter` attribute to `HLSLAttributedResourceType` and threads it through the AST, type printing, and mangling. It also adds a `__counter_handle` member to the relevant buffer types in `HLSLBuiltinTypeDeclBuilder`.
b562d70
to
9736c86
Compare
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few comments and nits. Thank you! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thing ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Just one small nit and an unused method that should be removed.
This is part 1 of implementing the typed buffer counters proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0023-typed-buffer-counters.md This patch adds the initial plumbing for supporting counter variables associated with structured buffers for the SPIR-V backend. It introduces an `IsCounter` attribute to `HLSLAttributedResourceType` and threads it through the AST, type printing, and mangling. It also adds a `__counter_handle` member to the relevant buffer types in `HLSLBuiltinTypeDeclBuilder`. Contributes to llvm#137032
This is part 1 of implementing the typed buffer counters proposal:
https://github.com/llvm/wg-hlsl/blob/main/proposals/0023-typed-buffer-counters.md
This patch adds the initial plumbing for supporting counter variables
associated with structured buffers for the SPIR-V backend. It introduces
an
IsCounter
attribute toHLSLAttributedResourceType
and threads itthrough the AST, type printing, and mangling. It also adds a
__counter_handle
member to the relevant buffer types inHLSLBuiltinTypeDeclBuilder
.Contributes to #137032